#ifndef TD_TURRET_H_
#define TD_TURRET_H_

/************************************************************************/
/* STL                                                                  */
/************************************************************************/
#include <map>

/************************************************************************/
/* CORE                                                                 */
/************************************************************************/
#include "Core/Utils.h"

/************************************************************************/
/* Game                                                                 */
/************************************************************************/
#include "Game/GameCore.h"
#include "Game/Managers/MarioManager.h"
#include "Game/Game Objects/Towers/Shots/BaseShot.h"
#include "Game/Factories/ShotFactory.h"

/************************************************************************/
/* GUI                                                                  */
/************************************************************************/
#include "GUI/Bars/ProgressBar.h"

#define NUMBER_OF_LEVELS 6

using namespace std;
using namespace TD_Core;
using namespace TD_Resources;
using namespace TD_GUI;


namespace TD_Game {

	class BaseTower : public BaseEntity {
	
	protected:
			
		/************************************************************************/
		/* Default values                                                       */
		/************************************************************************/
		static const unsigned int evolutionTime[NUMBER_OF_LEVELS];
		
		shared_ptr<SDLSound> pSound;
		/** BaseTower ID*/
		unsigned int m_ID;

		/************************************************************************/
		/* Private functions                                                    */
		/************************************************************************/
		/** Delete the shotted shots*/
		void deleteShots();

		typedef enum {
			shooting,
			idle,
			cooldown
		} towerStates;

		bool m_isShooting;


	protected:

		/** Variables responsible for the shooting interval management.*/
		int m_lastTick;

		/** The tower's description tile*/
		Tile *m_pDescriptionTile;

		/** The creep map from the system.*/
		const map<unsigned int, BaseMario *> *m_pCreeps;

		/** Animation set for rendering.*/
		AnimationSet * m_pAnimationSet;
		/** Current base shot, used to preallocate the tileset resource*/
		AnimationSet * m_pBaseShotAS;
		/** Base tower type. MUST BE INITIALIZED IN THE CHILD CLASSES*/
		towerTypes m_baseTowerType;
		/** Base tower type. MUST BE INITIALIZED IN THE CHILD CLASSES*/
		shotTypes m_baseShotType;

		/** Shotted shots.*/
		vector<BaseShot *> m_shotVector;
		

		/** Target creep.*/
		unsigned int m_targetID;
		BaseMario *m_pTarget;

		/** Upgrading information:*/
		ProgressBar *m_pProgressBar;
		bool m_isUpgrading;
		int m_upradingTick;
		Coord2D m_upBarDisplacement;

		/** Selling info: */
		bool m_isSelling;
		int m_sellingTick;
		bool m_wasSold;


		/************************************************************************/
		/* Tower stats                                                          */
		/************************************************************************/
		string m_towerName;
		string m_towerDescription;

		int m_shootingInterval[NUMBER_OF_LEVELS];
		unsigned int m_towerDamage[NUMBER_OF_LEVELS];
		unsigned int m_towerPrice[NUMBER_OF_LEVELS];
		unsigned int m_towerValue[NUMBER_OF_LEVELS];
		unsigned int m_towerRange[NUMBER_OF_LEVELS];
		unsigned int m_towerLvl;



		/************************************************************************/
		/* Protected functions                                                  */
		/************************************************************************/
		/** Initialization of the values*/
		void initValues();

		
		
		virtual void shoot();

	public:
		
		/************************************************************************/
		/* ctors and dtors                                                      */
		/************************************************************************/
		
		//Default
		explicit BaseTower();

		//Copy
		explicit BaseTower(const BaseTower &rhs);

		//Assignment
		BaseTower& operator=(const BaseTower &rhs);

		//Initialization
		explicit BaseTower(unsigned int g_ID, const Coord2D & turretPosition);
		
		//Dtor
		~BaseTower();


		/************************************************************************/
		/* Access functions                                                     */
		/************************************************************************/
		inline unsigned int getBaseTowerRadius() const {
			return(m_towerRange[m_towerLvl - 1]);
		}

		inline unsigned int getID() const {
			return(m_ID);
		}

		inline unsigned int getTowerLevel() const {
			return(m_towerLvl);
		}

		inline unsigned int getTowerRange() const {
			return(m_towerRange[m_towerLvl - 1]);
		}

		inline unsigned int getTowerDamage() const {
			return(m_towerDamage[m_towerLvl - 1]);
		}

		/*inline void setBaseTowerRadius(unsigned int turretRadius) {
			m_towerRange = turretRadius;
		}*/

		inline int getShootingInterval() const {
			return(m_shootingInterval[m_towerLvl - 1]);
		}


		/*inline void setShootingInterval(int shootingInterval) {
			m_shootingInterval = shootingInterval;
		}*/

		inline unsigned int getPrice() const {
			return(m_towerPrice[m_towerLvl - 1]);
		}

		inline unsigned int getDamage() const {
			return(m_towerDamage[m_towerLvl - 1]);
		}

		inline unsigned int getSellPrice() const {
			return(m_towerValue[m_towerLvl - 1 ]);
		}
		
		inline unsigned int getPriceToUpdate() const {
			if(m_towerLvl < NUMBER_OF_LEVELS) {
				return(m_towerPrice[m_towerLvl]);
			}
		}
		
		inline unsigned int getNextLevelDamage() const {
			if(m_towerLvl < NUMBER_OF_LEVELS) {
				return(m_towerDamage[m_towerLvl]);
			}
		}

		inline unsigned int getNextLevelRange() const {
			if(m_towerLvl < NUMBER_OF_LEVELS) {
				return(m_towerRange[m_towerLvl]);
			}
		}

		inline int getNextLevelCooldown() const {
			if(m_towerLvl < NUMBER_OF_LEVELS) {
				return(m_shootingInterval[m_towerLvl]);
			}
		}

		inline const string & getName() const {
			return(m_towerName);
		}

		inline const string & getDescription() const {
			return(m_towerDescription);
		}

		inline Tile * getDescriptionTile() const {
			return(m_pDescriptionTile);
		}


		inline bool isUpgrading() const {
			return(m_isUpgrading);
		}

		inline bool isSelling() const {
			return(m_isSelling);
		}

		inline bool wasSold() const{
			return(m_wasSold);
		}
		/************************************************************************/
		/* Functionalities                                                      */
		/************************************************************************/
		virtual void upgradeLevel();
		virtual void sell();

		/************************************************************************/
		/* Rendering                                                            */
		/************************************************************************/
		/** Updates with the external world */
		virtual void update(unsigned int deltaTime);
		void render(SDL_Surface *const g_destSurface, unsigned int deltaTime);

	};

}
#endif